package com.ai.service.made.impl;

import cn.hutool.core.lang.hash.Hash;
import com.ai.check.CameraCheck;
import com.ai.common.constant.CommonArgs;
import com.ai.common.CommonResponse;
import com.ai.common.exception.ServiceException;
import com.ai.entity.cameraFunctions.functions.CameraFunctionBindBO;
import com.ai.entity.cameraFunctions.functions.CameraFunctionsPO;
import com.ai.entity.function.FunctionPO;
import com.ai.entity.made.BaseIdOrNameBO;
import com.ai.entity.made.camera.*;
import com.ai.entity.network.L1ToIdentifySysMessage;
import com.ai.entity.security.SysUser;
import com.ai.entity.server.ServerPO;
import com.ai.model.vo.BatchOperateCameraParam;
import com.ai.model.vo.BxCameraInfoVo;
import com.ai.service.made.*;
import com.ai.util.HttpRequestUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sun.media.sound.MidiUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AlgorithmCameraServiceImpl implements AlgorithmCameraService {

    @Resource
    CameraService cameraService;
    @Resource
    TimeIntervalService timeIntervalService;
    @Resource
    RegionsService regionsService;
    @Resource
    ServerService serverService;
    @Resource
    FunctionService functionService;

    @Resource
    CameraFunctionsService cameraFunctionsService;
    @Value("${api.live.url}")
    private String liveUrl;
    @Value("${api.ai.url}")
    private String aiUrl;
    /**
     * 创建线程池，批量开启摄像头时使用
     */
    public static ExecutorService executorService = Executors.newFixedThreadPool(3);
    /**
     * 打开摄像头
     *
     * @param cameraIdBO
     */
    @Override
    public CommonResponse onOpen(CameraIdBO cameraIdBO) {

        int state = 2;

//        摄像头什么时候有效--查看操作的摄像头是否存在
        CameraPO cameraPO = cameraService.getCameraOn(cameraIdBO);
        if (cameraPO == null) {
            return CommonResponse.error("请选择有效设备");
        }
        int id = cameraPO.getId();
//        根据摄像头的id和状态批量操作直播
        CommonResponse commonResponse = bulkSwitchForLive(id, state);
//        switchForLive(id,state)
        //返回结果码：1成功，-1失败
        if (commonResponse.getCode() != 200) {
            return commonResponse;
        }
        cameraPO = new CameraPO();
        cameraPO.setState(1);
        cameraService.update(cameraPO, new QueryWrapper<CameraPO>().eq("id", id));
        CommonArgs.CAMERA_HEARTBEAT_MAP.put(id, System.currentTimeMillis());

        return CommonResponse.ok("开启成功");
    }

    /**
     * 关闭摄像头
     *
     * @param cameraIdBO
     */
    @Override
    public CommonResponse onClose(CameraIdBO cameraIdBO) {


        int state = 3;
//        CameraCheck cameraCheck = new CameraCheck();
////        鉴权
//        if (cameraCheck.isCurrentID(cameraIdBO.getCurrentId())) {
//            return cameraCheck.resultData;
//        }

        CameraPO cameraPO = cameraService.getCameraOn(cameraIdBO);
        if (cameraPO == null) {
            return CommonResponse.error("请选择有效设备");
        }

        int cameraId = cameraPO.getId();

        CommonResponse CommonResponse = bulkSwitchForLive(cameraId, state);
        if (CommonResponse.getCode() != 200) {
            return CommonResponse;
        }

        cameraPO.setState(2);
        cameraService.updateById(cameraPO);

        CommonArgs.CAMERA_HEARTBEAT_MAP.remove(cameraId);
        return CommonResponse.ok("关闭成功");
    }

    /**
     * 通过功能开关算法
     *
     * @param type
     * @param state
     */
    @Override
    public void bulkSwitchForTelegram(int type, int state, Integer delayTime) {
        bulkSwitchForTelegram(type, state, delayTime, null);
    }

    @Override
    public void bulkSwitchForTelegram(int type, int state, Integer delayTime, Map<String, Object> extendedProperties) {
        FunctionPO functionPO = functionService.getOne(new QueryWrapper<FunctionPO>().eq("type", type));
        List<SwitchCameraAlgorithmBO> switchCameraAlgorithmBOList = cameraFunctionsService.getCameraByType(functionPO, state, extendedProperties);

        for (SwitchCameraAlgorithmBO switchCameraAlgorithmBO : switchCameraAlgorithmBOList) {

            CameraPO cameraPO = cameraService.getById(switchCameraAlgorithmBO.getCameraId());
            int serverId = cameraPO.getServerId();
            if (serverId == 0) {
                throw new ServiceException("该摄像头未绑定服务器");
            }
            ServerPO server = serverService.getById(serverId);
            String ip = server.getIp();
            Integer port = server.getPort();
            if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || port == 0) {
                throw new ServiceException("该摄像头所绑定服务器未设置IP或端口");
            }
            String url = ("http://" + ip + ":" + port + "/") + aiUrl;


            new Thread(() -> {
                //延时开关
                if (delayTime != null && delayTime > 0) {
                    log.info("信号延迟【" + delayTime + "秒】启动");
                    try {
                        Thread.sleep(delayTime * 1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }

                String param = JSONObject.toJSONString(switchCameraAlgorithmBO);
                log.info("启停算法的指令为： " + param);

                String s = HttpRequestUtil.sendPost(url, param);

                if (StringUtils.isEmpty(s) || "null".equals(s)) {
                    log.info("网络请求失败！");
                    return;
                }
                JSONObject o = JSONObject.parseObject(s);
                int resultCode = Integer.valueOf(o.getString("result_code"));
                log.info("摄像头操作" + ((resultCode == -1) ? "失败" : "成功"));
            }).start();
        }
    }

    @Override
    public CommonResponse detectionStart() {

        String url = "http://192.168.8.153:5000/predict";

//        String param = JSONObject.toJSONString(message);

        String param ="{\n" +
                "    \"cameraCode\":\"code\",\n" +
                "    \"cameraId\":1133,\n" +
                "    \"detectionTimes\":0,\n" +
                "    \"functions\":[\n" +
                "        {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1101\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1102\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1103\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1104\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1105\n" +
                "        }, {\n" +
                "            \"code\":\"2101\",\n" +
                "            \"id\":2101,\n" +
                "            \"spots\":[\n" +
                "                {\n" +
                "                    \"id\":100,\n" +
                "                    \"spots\":[\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":1\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":959,\n" +
                "                            \"y\":539\n" +
                "                        },\n" +
                "                        {\n" +
                "                            \"x\":1,\n" +
                "                            \"y\":539\n" +
                "                        }\n" +
                "                    ]\n" +
                "                }\n" +
                "            ],\n" +
                "            \"threshold\":0,\n" +
                "            \"timeIntervals\":[\n" +
                "                {\n" +
                "                    \"endTime\":\"235959\",\n" +
                "                    \"startTime\":\"000000\"\n" +
                "                }\n" +
                "            ],\n" +
                "            \"type\":1105\n" +
                "        }\n" +
                "    ],\n" +
                "    \"ip\":\"192.168.8.153\",\n" +
                "    \"password\":\"123123\",\n" +
                "    \"planNo\":\"1234\",\n" +
                "    \"status\":4,\n" +
                "    \"streamWay\":1,\n" +
                "    \"url\":\"/home/server/cfc/video_file/bgs/phone_bgs/louxia1.mp4\",\n" +
                "    \"username\":\"camera_account\"\n" +
                "}";
        String s = HttpRequestUtil.sendPost(url, param);

        if (StringUtils.isEmpty(s) || "null".equals(s)) {
            log.info("网络请求失败！");
            return null;
        }

        JSONObject o = JSONObject.parseObject(s);
        int resultCode = Integer.valueOf(o.getString("resultCode"));
        log.info("摄像头操作" + ((resultCode == -1) ? "失败" : "成功"));

        return CommonResponse.ok("功能开启成功");
    }

    @Override
    public CommonResponse batchOpening(BatchOperateCameraParam batchOperateCameraParam) {

        //需要操作的摄像头id
        List<Integer> cameraIds = batchOperateCameraParam.getCameraIds();
        //开启还是关闭操作
        Integer state = batchOperateCameraParam.getState();

        if (CollectionUtils.isNotEmpty(cameraIds)){
            for (Integer cameraId : cameraIds) {
                //向线程池提交任务
                executorService.submit(()->{

                    CommonResponse response = bulkSwitchForLive(cameraId, state);

                    if (response.getCode()==200){
                        if (state==2  ){
                            //开启直播
                            cameraService.update(new UpdateWrapper<CameraPO>().eq("id", cameraId).set("state","1"));
                            CommonArgs.CAMERA_HEARTBEAT_MAP.put(cameraId, System.currentTimeMillis());
                        }else if (state==3 ){
                            //关闭直播
                            cameraService.update(new UpdateWrapper<CameraPO>().eq("id", cameraId).set("state","2"));
                            CommonArgs.CAMERA_HEARTBEAT_MAP.remove(cameraId);
                        }
                    }
                    //操作失败不做处理
                });
            }
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return CommonResponse.ok("操作完成");
    }

    @Transactional
    @Override
    public CommonResponse receiveCameraInfo(List<ReceiveCameraInfoBx> cameraInfoBxList) {

        if (CollectionUtils.isNotEmpty(cameraInfoBxList)){

            //数据校验
            cameraInfoBxList.forEach(item->{
                if (null == item.getCode()){
                    throw new RuntimeException("摄像头code不能为空");
                }
                if (null == item.getUrl()){
                    throw new RuntimeException("取流地址不能为空");
                }
                if (CollectionUtils.isEmpty(item.getFunctionTypes())){
                    throw new RuntimeException("摄像头绑定的功能type值不能为空");
                }
            });

            //检测当前入参的摄像头code是否存在重复的
            Set<String> codeSet = cameraInfoBxList.stream().map(ReceiveCameraInfoBx::getCode).collect(Collectors.toSet());
            if (codeSet.size() != cameraInfoBxList.size()){
                throw new RuntimeException("禁止传入的重复的摄像头code");
            }

//            Map<String, List<String>> codeFunctionMap = cameraInfoBxList.stream()
//                    .collect(Collectors.toMap(ReceiveCameraInfoBx::getCode, ReceiveCameraInfoBx::getFunctionTypes));

            //校验所有的type值是否合法
            ArrayList<String> voAllFunctionTypeList = new ArrayList<>();
            for (ReceiveCameraInfoBx receiveCameraInfoBx : cameraInfoBxList) {
                List<String> functionTypes = receiveCameraInfoBx.getFunctionTypes();
                voAllFunctionTypeList.addAll(functionTypes);
            }
            List<String> voFunctionTypeList = voAllFunctionTypeList.stream().distinct().collect(Collectors.toList());
            List<Integer> voFunctionTypeIntegerList = voFunctionTypeList.stream().map(Integer::valueOf).collect(Collectors.toList());
            //获取所有的功能type值
            List<Integer> dbAllFunctionTypeList = functionService.list().stream().map(FunctionPO::getType).collect(Collectors.toList());
            if(!dbAllFunctionTypeList.containsAll(voFunctionTypeIntegerList)){
                return CommonResponse.error("传入的功能type值不合法");
            }

            //获取所有摄像头对应的功能id值，并封装为map
            HashMap<String, List<Integer>> bindCameraIdFunctionIdMap = new HashMap<>(16);
            for (ReceiveCameraInfoBx receiveCameraInfoBx : cameraInfoBxList) {
                List<Integer> bindFunctionIdList = functionService.list(new QueryWrapper<FunctionPO>()
                        .in("type", receiveCameraInfoBx.getFunctionTypes())).stream()
                        .map(FunctionPO::getId).collect(Collectors.toList());
                bindCameraIdFunctionIdMap.put(receiveCameraInfoBx.getCode(),bindFunctionIdList);
            }

            LinkedList<CameraPO> updateCameraList = new LinkedList<>();
            LinkedList<String> updateCameraCodeList = new LinkedList<>();
            //校验每个摄像头code值是否已经在db中存在
            codeSet.forEach(item->{
                CameraPO cameraDbPo = cameraService.getOne(new QueryWrapper<CameraPO>().eq("code", item).gt("state", 0));
                /**
                 * code值已存在，执行更新操作
                 */
                if (null != cameraDbPo) {
                    List<ReceiveCameraInfoBx> receiveCameraInfoBxList = cameraInfoBxList.stream()
                            .filter(receiveCameraInfoBx -> receiveCameraInfoBx.getCode().equals(item)).collect(Collectors.toList());
                    ReceiveCameraInfoBx receiveCameraInfoBx = receiveCameraInfoBxList.get(0);
                    cameraDbPo.setUrl(receiveCameraInfoBx.getUrl());
                    updateCameraList.add(cameraDbPo);
                    updateCameraCodeList.add(item);
                }
            });
            //批量更新摄像头
            if (CollectionUtils.isNotEmpty(updateCameraList)){
                cameraService.updateBatchById(updateCameraList);
                batchBindCameraFunction(bindCameraIdFunctionIdMap,updateCameraList,false);
            }

            //筛选出需要新增的实例
            List<ReceiveCameraInfoBx> newReceiveCameraInfoBxList = cameraInfoBxList.stream()
                    .filter(receiveCameraInfoBx -> !updateCameraCodeList.contains(receiveCameraInfoBx.getCode())).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(newReceiveCameraInfoBxList)){
                //开始准备摄像头实例新增
                List<CameraPO> cameraPoList = getNeedAddCameraList(newReceiveCameraInfoBxList);
                //批量保存
                cameraService.saveBatch(cameraPoList);
                batchBindCameraFunction(bindCameraIdFunctionIdMap, cameraPoList,true);
            }


            return CommonResponse.ok("摄像头信息已接受");
        }
        return CommonResponse.ok("摄像头信息已接受");
    }

    private CommonResponse<Object> checkType(List<ReceiveCameraInfoBx> cameraInfoBxList) {

        return null;
    }

    /**
     * 组装需要新增的camera实例
     * @param newReceiveCameraInfoBxList 从宝信接口下发需要新增的实例
     * @return 实例list集合
     */
    private static List<CameraPO> getNeedAddCameraList(List<ReceiveCameraInfoBx> newReceiveCameraInfoBxList) {
        return newReceiveCameraInfoBxList.stream().map(receiveCameraInfoBx -> {
            CameraPO cameraPo = new CameraPO();
            BeanUtils.copyProperties(receiveCameraInfoBx, cameraPo);
            cameraPo.setCreateTime(new Date());
            cameraPo.setUpdateTime(new Date());
            cameraPo.setServerId(1);
            cameraPo.setState(2);
            cameraPo.setMaxNum(200);
            return cameraPo;
        }).collect(Collectors.toList());
    }

    /**
     * 绑定摄像头功能关系
     * @param bindCameraIdFunctionIdMap  cameraCode 和 functionIdList map集合
     * @param cameraPoList 操作的摄像头集合
     * @param isAddNewRelation 是否为新增
     */
    private void batchBindCameraFunction(Map<String, List<Integer>> bindCameraIdFunctionIdMap, List<CameraPO> cameraPoList,boolean isAddNewRelation) {
        //开始批量绑定摄像头功能信息
        cameraPoList.forEach(camera ->{

            CameraFunctionBindBO cameraFunctionBindBO = new CameraFunctionBindBO();
            cameraFunctionBindBO.setCameraId(camera.getId());

            List<Integer> voBindFunctionIds = bindCameraIdFunctionIdMap.get(camera.getCode());

            if (isAddNewRelation){
                cameraFunctionBindBO.setFunctionIds(voBindFunctionIds);
//                SysUser sysUser = (SysUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
                //第三方接口，获取不到用户id，直接使用99999
                cameraFunctionBindBO.setCurrentId(99999);
                cameraFunctionsService.checked(cameraFunctionBindBO);
            }else {
                //为批量更新，先检测之前的功能是否需要解绑
                List<CameraFunctionsPO> dbBindedFunctionsList = cameraFunctionsService.list(new QueryWrapper<CameraFunctionsPO>()
                        .select("function_id").eq("camera_id", camera.getId()));

                if (CollectionUtils.isNotEmpty(dbBindedFunctionsList)){
                    //已经绑定过的功能id列表
                    List<Integer> dbFunctionIdList = dbBindedFunctionsList.stream()
                            .map(CameraFunctionsPO::getFunctionId).collect(Collectors.toList());

                    //需要移除的功能id列表
                    List<Integer> needRemoveFunctionIdList = dbFunctionIdList.stream().filter(dbBindFunctionId -> !voBindFunctionIds.contains(dbBindFunctionId)).collect(Collectors.toList());

                    if (CollectionUtils.isNotEmpty(needRemoveFunctionIdList)){
                        //进行移除操作
                        cameraFunctionsService.remove(new QueryWrapper<CameraFunctionsPO>().eq("camera_id",camera.getId()).in("function_id",needRemoveFunctionIdList));
                    }

                    //需要新增的功能id列表
                    List<Integer> needAddFunctionIdList = voBindFunctionIds.stream().filter(voBindFunctionId -> !dbFunctionIdList.contains(voBindFunctionId)).collect(Collectors.toList());

                    if (CollectionUtils.isNotEmpty(needAddFunctionIdList)){
                        if (CollectionUtils.isNotEmpty(needAddFunctionIdList)){
//                            List<Integer> addFunctionIds = needAddFunctionIdList.stream().map(Integer::parseInt).collect(Collectors.toList());
                            cameraFunctionBindBO.setFunctionIds(needAddFunctionIdList);
                            cameraFunctionBindBO.setCurrentId(99999);
                            cameraFunctionsService.checked(cameraFunctionBindBO);
                        }
                    }

                }




            }


        });
    }

    @Override
    public CommonResponse cameraSwitch(CameraSwitch cameraSwitch) {

        String code = cameraSwitch.getCode();
        if (null == code){
            throw new RuntimeException("摄像头code不能为空");
        }
        CameraPO cameraPO = cameraService.getByCode(code);
        if (null == cameraPO){
            throw new RuntimeException("code没有对应的摄像头");
        }

//        CommonResponse commonResponse = bulkSwitchForLive(cameraPO.getId(), Integer.parseInt(cameraSwitch.getState()));
//
//         TODO: 2024-11-12 steam未部署，暂先不请求算法
//        commonResponse.setCode(200);
//
//        //返回结果码：1成功，-1失败
//        if (commonResponse.getCode() != 200) {
//            return commonResponse;
//        }

//        cameraPO = new CameraPO();
        cameraPO.setState(Integer.valueOf(cameraSwitch.getState()));
        cameraService.update(cameraPO, new QueryWrapper<CameraPO>().eq("id", cameraPO.getId()));
//        CommonArgs.CAMERA_HEARTBEAT_MAP.put(cameraPO.getId(), System.currentTimeMillis());

        return CommonResponse.ok("1".equals(cameraSwitch.getState())?"开启成功":"关闭成功");
    }

    @Override
    public CommonResponse getCameraState(List<String> cameraCodeList) {

        if (CollectionUtils.isNotEmpty(cameraCodeList)){
            List<CameraPO> cameraPOList = cameraService.list(new QueryWrapper<CameraPO>().in("code", cameraCodeList));
            List<BxCameraInfoVo> bxCameraInfoVoList = cameraPOList.stream().map(cameraPO -> {
                BxCameraInfoVo bxCameraInfoVo = new BxCameraInfoVo();
                List<CameraFunctionsPO> cameraFunctionsPOList = cameraFunctionsService.list(new QueryWrapper<CameraFunctionsPO>().eq("camera_id", cameraPO.getId()));
                if (CollectionUtils.isNotEmpty(cameraFunctionsPOList)) {
                    List<Integer> functionIdList = cameraFunctionsPOList.stream().map(CameraFunctionsPO::getFunctionId).collect(Collectors.toList());
                    List<FunctionPO> functionPOList = functionService.list(new QueryWrapper<FunctionPO>().in("id", functionIdList));
                    List<Integer> functionTypeList = functionPOList.stream().map(FunctionPO::getType).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(functionTypeList)){
                        bxCameraInfoVo.setFunctionTypeList(functionTypeList);
                    }
                }
                bxCameraInfoVo.setCameraId(cameraPO.getId());
                bxCameraInfoVo.setCameraState(cameraPO.getState());
                bxCameraInfoVo.setUrl(cameraPO.getUrl());
                bxCameraInfoVo.setCameraCode(cameraPO.getCode());
                return bxCameraInfoVo;
            }).collect(Collectors.toList());
            return CommonResponse.ok(bxCameraInfoVoList);
        }else {
            throw new RuntimeException("摄像头id列表不能为空");
        }
    }


    /**
     * 直播开关
     *
     * @param cameraId
     * @param state    2、3对应开启直播、关闭直播
     * @return
     */
    private CommonResponse bulkSwitchForLive(int cameraId, int state) {
        log.info("===========================  任务正在执行，当前线程：{}  ===========================",Thread.currentThread().getName());
        CameraPO cameraPO = cameraService.getById(cameraId);
        //服务器id
        int serverId = cameraPO.getServerId();
        if (serverId == 0) {
            return CommonResponse.error("该摄像头未绑定服务器");
        }
//        通过服务器ip获取对应的服务器
        ServerPO server = serverService.getById(serverId);
        if (null == server){
            return CommonResponse.error("服务器不存在，请检查摄像头后重新操作");
        }
        String ip = server.getIp();
        Integer port = server.getPort();
        if (StringUtils.isEmpty(ip) || StringUtils.isEmpty(port) || port == 0) {
            return CommonResponse.error("该摄像头所绑定服务器未设置IP或端口");
        }
        String url = ("http://" + ip + ":" + port + "/") + liveUrl;

        List<SwitchCameraFunctionAlgorithmBO> functionAlgorithmBOList =getAlgorithmFunctions(cameraId);

        String param;
//        摄像头与算法实体
        CameraSwitchAlgorithmBO algorithmBO = new CameraSwitchAlgorithmBO();
        if (state == 3) {
            //关闭直播
            algorithmBO.setCameraId(cameraId);
            algorithmBO.setState(3);
            algorithmBO.setUrl("");
            algorithmBO.setCameraCode(cameraPO.getCode());
            algorithmBO.setStatus(3);
            param = JSONObject.toJSONString(algorithmBO);

            log.info("------[" + cameraPO.getCode() + "]关闭直播");

        } else {
            //打开直播
            SwitchCameraAlgorithmBO switchCameraAlgorithmBO = new SwitchCameraAlgorithmBO();
            BeanUtils.copyProperties(cameraPO, switchCameraAlgorithmBO);
            switchCameraAlgorithmBO.setCameraId(cameraId);
            switchCameraAlgorithmBO.setCameraCode(cameraPO.getCode());
            switchCameraAlgorithmBO.setFunctions(functionAlgorithmBOList);
            log.info("------[" + cameraPO.getCode() + "]开启直播");

            switchCameraAlgorithmBO.setState(state);
            switchCameraAlgorithmBO.setStatus(state);
            param = JSONObject.toJSONString(switchCameraAlgorithmBO);
        }

        log.info("===========================  算法入参：{}  ===========================",param);


        String sr = HttpRequestUtil.sendPost(url, param);

        if (StringUtils.isEmpty(sr) || "null".equals(sr)) {//会返会null字符串么
            return CommonResponse.error("网络请求失败！");
        }
        //解析算法返回数据
        JSONObject jsonObject = JSONObject.parseObject(sr);
        String alReturnJson = jsonObject.toJSONString();

        log.info("===========================  算法返回数据：{} ===========================",alReturnJson);


        //返回结果码：1成功，-1失败
        int result = Integer. valueOf(jsonObject.getString("resultCode"));
        String msg = jsonObject.getString("resultMsg");
        if (result == -1) {
            return CommonResponse.error("摄像头操作失败：" + msg);
        }
        return CommonResponse.ok("操作成功");
    }

    /**
     * 获取摄像头所绑定方法的所有区域信息
     * @param cameraId
     * @return
     */
    private List<SwitchCameraFunctionAlgorithmBO> getAlgorithmFunctions( int cameraId ) {
        //获取当前摄像头所绑定的所有方法
        ArrayList<SwitchCameraFunctionAlgorithmBO> functionList = new ArrayList<>();
        List<CameraFunctionsPO> cameraFunctionsPOList= cameraFunctionsService.getBindFunctions(cameraId);


        for (CameraFunctionsPO cameraFunctionsPO : cameraFunctionsPOList) {

            FunctionPO functionPO = functionService.getById(cameraFunctionsPO.getFunctionId());
            if (null == functionPO){
                throw new RuntimeException("摄像头绑定的功能不存在，请检查后重新操作");
            }
            int type = functionPO.getType();

            SwitchCameraFunctionAlgorithmBO functionAlgorithmBO = new SwitchCameraFunctionAlgorithmBO();
            functionAlgorithmBO.setId(cameraFunctionsPO.getId()).setType(type + "")
                    .setThreshold(cameraFunctionsPO.getThreshold())
                    .setSpecialOne(cameraFunctionsPO.getSpecialOne())
                    .setSpecialThree(cameraFunctionsPO.getSpecialTwo())
                    .setSpecialThree(cameraFunctionsPO.getSpecialThree())
                    .setSpecialFour(cameraFunctionsPO.getSpecialFour())
                    .setSpecialFive(cameraFunctionsPO.getSpecialFive())
                    .setTimeIntervals(timeIntervalService.getTimeIntervalList(cameraFunctionsPO.getId()))
                    .setSpots(regionsService.getSpots(cameraFunctionsPO.getId()));
            functionList.add(functionAlgorithmBO);
        }

        return functionList;
    }
}
